﻿using System;
using System.Collections.Generic;
using System.Text;
using JsonSharp;
using Barbar.MapReport.HtmlRender.Handlers;
using System.IO;
using System.IO.Compression;
using System.Xml.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace Barbar.MapReport.HtmlRender {
  internal abstract class MapCallbackService {
    internal abstract JsonValue ProcessCallback(MapCallbackData callbackData);
    internal abstract string JavaScriptFunctionName { get; }
    
    protected object GetValue(MapCallbackData callbackData) {
      if (callbackData.ContainsKey(GetType().FullName)) {
        return Deserialize(callbackData[GetType().FullName]);
      } else {
        return HtmlRenderCacheManager.GetCallbackItem(callbackData.CallbackId, GetType().FullName);
      }
    }

    private object Deserialize(string data) {
      object result;
      BinaryFormatter formatter = new BinaryFormatter();
      using (MemoryStream stream = new MemoryStream(Convert.FromBase64String(data))) {
        using (DeflateStream compressStream = new DeflateStream(stream, CompressionMode.Decompress)) {
          result = formatter.Deserialize(compressStream);
          compressStream.Close();
        }
        stream.Close();
      }
      return result;
    }

    internal string Serialize(object instance) {
      string base64data;
      BinaryFormatter formatter = new BinaryFormatter();
      using (MemoryStream stream = new MemoryStream()) {
        using (DeflateStream compressStream = new DeflateStream(stream, CompressionMode.Compress)) {
          formatter.Serialize(compressStream, instance);
          compressStream.Close();
        }
        base64data = Convert.ToBase64String(stream.ToArray());
        stream.Close();
      }

      StringBuilder result = new StringBuilder();
      foreach (char c in base64data) {
        if (c == '+') {
          result.Append("%2B");
          continue;
        }
        if (c == '/') {
          result.Append("%2F");
          continue;
        }
        result.Append(c);
      }

      return result.ToString();
    }
  }
}
